package tum0r.json;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 工程: XJSON<br>
 * 包: tum0r.json<br>
 * 创建者: tum0r<br>
 * 创建时间: 2020/9/15 14:14<br>
 * <br>
 */
public class JSONObject extends JSON {
    public JSONObject() {
        super();
    }

    private static JSONObject parseString(String data) {
        JSONObject result = new JSONObject();
        if (data != null && data.trim().length() != 0) {
            Pattern pattern = Pattern.compile("\\{(.*)\\}");
            Matcher matcher = pattern.matcher(data);
            if (matcher.find()) {
                data = matcher.group(1);
                while (!data.equals("")) {
                    int index = data.indexOf(":");
                    if (index != -1) {
                        String key = data.substring(0, index).trim().replace("\"", "");
                        if (data.length() > index + 1) {
                            data = data.substring(index + 1).trim();
                            if (data.charAt(0) == '{') {
                                int end;
                                int state = 1;
                                for (end = 1; end < data.length(); end++) {
                                    if (data.charAt(end) == '{') {
                                        state++;
                                    } else if (data.charAt(end) == '}') {
                                        state--;
                                    }
                                    if (state == 0) {
                                        break;
                                    }
                                }
                                end++;
                                result.put(key, JSONObject.parse(data.substring(0, end)));
                                if (data.length() > end) {
                                    data = data.substring(end + 1).trim();
                                    if (data.startsWith(",")) {
                                        data = data.substring(1).trim();
                                    }
                                } else if (data.length() == end) {
                                    data = "";
                                }
                            } else if (data.charAt(0) == '[') {
                                int end;
                                int state = 1;
                                for (end = 1; end < data.length(); end++) {
                                    if (data.charAt(end) == '[') {
                                        state++;
                                    } else if (data.charAt(end) == ']') {
                                        state--;
                                    }
                                    if (state == 0) {
                                        break;
                                    }
                                }
                                end++;
                                result.put(key, JSONArray.parse(data.substring(0, end)));
                                if (data.length() > end) {
                                    data = data.substring(end + 1).trim();
                                    if (data.startsWith(",")) {
                                        data = data.substring(1).trim();
                                    }
                                } else if (data.length() == end) {
                                    data = "";
                                }
                            } else {
                                index = data.indexOf(",");
                                if (index != -1) {
                                    result.put(key, parseValue(data.substring(0, index)));
                                    if (data.length() > index + 1) {
                                        data = data.substring(index + 1).trim();
                                    }
                                } else {
                                    result.put(key, parseValue(data));
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
        return result;
    }

    private static JSONObject parseCollection(Object data) {
        JSONObject result = new JSONObject();
        if (data instanceof Collection) {
            Collection<Object> collection = (Collection<Object>) data;
            if (collection.size() > 0) {
                JSONArray temp = new JSONArray();
                for (Object o : collection) {
                    if (o instanceof Collection) {
                        temp.put(JSONArray.parse(o));
                    } else if (o instanceof Map || o instanceof Enumeration || o instanceof Dictionary) {
                        temp.put(JSONObject.parse(o));
                    } else {
                        temp.add(JSONWriter.serialize(o));
                    }
                }
                if (temp.count() > 0) {
                    result.put(null, temp);
                }
            }
        } else if (data instanceof Map || data instanceof Enumeration || data instanceof Dictionary) {
            Iterator<Object> iterator;
            if (data instanceof Map) {
                iterator = ((Map<Object, Object>) data).keySet().iterator();
            } else if (data instanceof Enumeration) {
                iterator = ((Enumeration) data).asIterator();
            } else {
                iterator = ((Dictionary) data).keys().asIterator();
            }
            if (iterator != null) {
                while (iterator.hasNext()) {
                    Object key = iterator.next();
                    Object valueObject;
                    if (data instanceof Map) {
                        valueObject = ((Map<Object, Object>) data).get(key);
                    } else if (data instanceof Enumeration) {
                        valueObject = key;
                        key = null;
                    } else {
                        valueObject = ((Dictionary) data).get(key);
                    }
                    if (valueObject instanceof Collection) {
                        if (key != null) {
                            if (key instanceof Collection) {
                                result.put(JSONArray.parse(key).toString(), JSONArray.parse(valueObject));
                            } else if (key instanceof Map || key instanceof Enumeration || key instanceof Dictionary) {
                                result.put(JSONObject.parse(key).toString(), JSONArray.parse(valueObject));
                            } else {
                                result.put(key.toString(), JSONArray.parse(valueObject));
                            }
                        } else {
                            result.put(null, JSONArray.parse(valueObject));
                        }
                    } else if (valueObject instanceof Map || valueObject instanceof Enumeration || valueObject instanceof Dictionary) {
                        if (key != null) {
                            if (key instanceof Collection) {
                                result.put(JSONArray.parse(key).toString(), JSONObject.parse(valueObject));
                            } else if (key instanceof Map || key instanceof Enumeration || key instanceof Dictionary) {
                                result.put(JSONObject.parse(key).toString(), JSONObject.parse(valueObject));
                            } else {
                                result.put(key.toString(), JSONObject.parse(valueObject));
                            }
                        } else {
                            result.put(null, JSONObject.parse(valueObject));
                        }
                    } else {
                        result.put(key == null ? null : key.toString(), valueObject);
                    }
                }
            }
        } else {
            result.put(data.toString());
        }
        return result;
    }

    public static JSONObject parse(Object data) {
        JSONObject result = new JSONObject();
        if (data != null) {
            if (!data.getClass().isArray()) {
                if (data instanceof String) {
                    String temp = ((String) data).trim();
                    Pattern pattern = Pattern.compile("\\{(.*)\\}");
                    Matcher matcher = pattern.matcher(temp);
                    if (matcher.find()) {
                        if (temp.startsWith("{") && temp.endsWith("}")) {
                            result.put(JSONObject.parseString(temp));
                        }
                    } else {
                        result.put(data);
                    }
                } else if (data instanceof Collection) {
                    result.put(JSONArray.parse(data));
                } else if (data instanceof Map || data instanceof Dictionary || data instanceof Enumeration) {
                    result.put(JSONObject.parseCollection(data));
                } else if (data instanceof JSON) {
                    result.put((JSON) data);
                } else {
                    result.put(data);
                }
            } else {
                result.put(JSONArray.parse(data));
            }
        }
        return result;
    }

    public static JSONObject serialize(Object data) {
        return JSONObject.parse(JSONWriter.serialize(data));
    }

    public boolean put(String key, Object value) {
        return super.put(key, value);
    }

    public boolean put(Object value) {
        return super.put(count() + "", value);
    }

    public Object getObject(String key) {
        return getJsonNode(key).getObject();
    }

    public Object getObjectOrDefault(String key, Object defaultResult) {
        Object result = getObject(key);
        return result != null ? result : defaultResult;
    }

    public byte getByte(String key) {
        return getJsonNode(key).getByte();
    }

    public short getShort(String key) {
        return getJsonNode(key).getShort();
    }

    public int getInt(String key) {
        return getJsonNode(key).getInt();
    }

    public long getLong(String key) {
        return getJsonNode(key).getLong();
    }

    public Date getDate(String key) {
        return getJsonNode(key).getDate();
    }

    public float getFloat(String key) {
        return getJsonNode(key).getFloat();
    }

    public double getDouble(String key) {
        return getJsonNode(key).getDouble();
    }

    public boolean getBoolean(String key) {
        return getJsonNode(key).getBoolean();
    }

    public char getChar(String key) {
        return getJsonNode(key).getChar();
    }

    public String getString(String key) {
        return getJsonNode(key).getString();
    }

    public JSONObject getJSONObject(String key) {
        return getJsonNode(key).getJSONObject();
    }

    public JSONArray getJSONArray(String key) {
        return getJsonNode(key).getJSONArray();
    }

    private String JSONNodeToString(JSONNode node) {
        StringBuilder result = new StringBuilder();
        if (node != null) {
            result.append(JSONNodeToString(node.leftNode));
            result.append("\"");
            result.append(node.key);
            result.append("\": ");
            result.append(node.toString());
            result.append(", ");
            result.append(JSONNodeToString(node.rightNode));
        }
        return result.toString();
    }

    @Override
    public String toString() {
        StringBuilder result = new StringBuilder();
        result.append("{");
        if (rootNode != null && rootNode.key != null) {
            String temp = JSONNodeToString(rootNode);
            result.append(temp, 0, temp.length() - 2);
        }
        result.append("}");
        return result.toString();
    }
}
